home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / asmbler.arc / DESEQ.ASM < prev    next >
Assembly Source File  |  1988-11-19  |  15KB  |  398 lines

  1. COMMENT \
  2. Filter TOPS-20 sequence  numbers from  the standard  input file.   These
  3. consist of sequences nnnn<Bn><09> at  the beginning of each line.   That
  4. is, the fifth character is a digit <3n> which has been OR'ed with  <80>.
  5. This is how Kermit flags the  fifth character from a DEC-20 36-bit  word
  6. in which the rightmost bit is 1.  Trailing blanks are also trimmed.   If
  7. any single line is longer  than the internal line buffer size (256),  it 
  8. will be output unprocessed and a warning  message will be issued.   This
  9. should be rare,  and if the number of occurrences is small, hand editing
  10. of the output file could fix the problem.
  11.  
  12. Usage:  deseq <inputfile >outputfile
  13.  
  14. Error return codes:
  15.         0 - normal termination
  16.         1 - write error on standard output file (usually because disk full);
  17.             an error message is printed.
  18.  
  19. {Adapted from a disassembly of the IBM utility MORE.COM and commented
  20. with a view to being a model for further simple filters.}
  21.  
  22. For efficiency, input and output characters are handled in large buffers.
  23.  
  24. [28-Jan-84]
  25. \
  26.  
  27. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  28. deseqc  segment para public 'code'
  29.  
  30. include dos.inc
  31. include ascii.inc
  32.  
  33.         org     100h            ; this is a .COM file
  34. DEBUG   equ     0               ; non-zero for built-in input file test
  35.  
  36. ; Sum of buffer sizes can be 64K-(code + otherdata size), or about 40K total
  37.  
  38. MAXOUTBUF       equ     16384   ; Output buffer size
  39. MAXINBUF        equ     16384   ; Input buffer size
  40. MAXLINBUF       equ       256   ; Line buffer size
  41.  
  42. deseq   proc    near
  43.         call    check_dos_version
  44. if DEBUG
  45.         mov     dx,offset debugfn
  46.         mov     al,$DOS_OPEN2_READ
  47.         mov     ah,$DOS_OPEN2
  48.         int     $DOS
  49.         jnc     openok
  50.         int     $HALT           ; open failure
  51. openok:
  52.         mov     debugin,ax      ; save file handle
  53. endif
  54.         mov     inbuf_prev,0    ; set empty input buffer
  55.         mov     inbuf_len,0     ; set empty input buffer
  56.         mov     linbuf_len,0    ; set empty line buffer
  57.         mov     outbuf_len,0    ; set empty output buffer
  58.  
  59. readln:
  60.         call    get_line        ; get an input line
  61.         mov     cx,linbuf_len   ; Get output line length
  62.         jcxz    eof             ; No more data, all done
  63.         call    strip_line      ; Yes, go strip any line number
  64.  
  65. putlin:
  66.         call    trim_line
  67.         call    write_line      ; go write the line
  68.         jmp     short readln    ; Loop for next line
  69.  
  70. eof:                            ; here at end-of-file
  71.         call    write_buf       ; write any remaining data
  72.         mov     ah,$DOS_EXIT    ; all done, no more data
  73.         mov     al,0            ; return code
  74.         int     $DOS            ; terminate
  75.  
  76. if DEBUG
  77.         even                     ; align on word boundary
  78. debugin dw      ?        
  79. debugfn db      "c:\pascal\foo.for",.NUL
  80. endif
  81.         even                            ; align on word boundary
  82. inbuf_prev dw   ?                       ; Buffer pointer
  83. inbuf_len dw    ?                       ; Buffer size
  84. inbuf     db    MAXINBUF dup (?)        ; Input buffer
  85.  
  86.         even                            ; align on word boundary
  87. linbuf_len dw   ?                       ; Buffer pointer
  88. linbuf     db   MAXLINBUF dup (?)       ; Output buffer for line storage
  89.  
  90.         even                            ; align on word boundary
  91. outbuf_len dw   ?                       ; Buffer length 
  92. outbuf     db   MAXOUTBUF dup (?)       ; Output buffer for final write
  93. deseq   endp
  94.  
  95. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  96. trim_line proc  near
  97.  
  98. ; Routine to trim trailing white space from line.  No action is taken if
  99. ; the line buffer does not end with CR LF, since in that case, the line
  100. ; is incomplete (long line split across buffer boundary).
  101. ; No registers are preserved
  102.  
  103.         mov     cx,linbuf_len   ; line length
  104.         mov     si,offset linbuf-3      ; output buffer address-3
  105.         add     si,cx           ; address of last character before CR LF
  106.  
  107.         mov     al,[si+1]       ; get what should be CR
  108.         cmp     al,.CR          ; was it?
  109.         jne     notrim          ; no, not really end-of-line
  110.         
  111.         mov     al,[si+2]       ; get what should be LF
  112.         cmp     al,.LF          ; was it?
  113.         jne     notrim          ; no, not really end-of-line
  114.  
  115.         std                     ; set direction flag to decrement si
  116.  
  117. trim:
  118.         lodsb                   ; byte from [si] to al, decrement si
  119.         cmp     al," "          ; blank?
  120.         je      zap_space       ; yes
  121.         cmp     al,.HT          ; tab?
  122.         jne     notrim          ; no, not white space, so exit loop
  123. zap_space:
  124.         mov     byte ptr [si+1],.NUL     ; change blank or tab to NUL
  125.         loop    trim            ; decrement cx and loop until cx = 0
  126.  
  127. notrim:
  128.         ret                     ; return to caller
  129.  
  130. trim_line endp      
  131.  
  132. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  133. strip_line proc near
  134.  
  135. ; Routine to strip line numbers
  136. ; No registers are preserved
  137.  
  138.         mov     cx,linbuf_len   ; line length
  139.         cmp     cx,8            ; Possible nnnnn<TAB> .. <CR><LF> on this line?
  140.         jle     strip_done      ; No, return immediately
  141.         mov     si,offset linbuf; line buffer address
  142.         cld                     ; clear direction flag to increment si
  143.  
  144. nextch:                         ; Loop looking for line numbers
  145.         lodsb                   ; Byte from [si] to al, increment si
  146.         cmp     al,128          ; 8-th bit on?
  147.         jb      ordchr          ; Jump if not
  148.         call    check_seq       ; Check for sequence number and clear if so
  149. ordchr:                         ; Ordinary character
  150.         loop    nextch          ; Decrement count in cx and loop until cx = 0
  151.  
  152. strip_done:
  153.         ret                     ; return to caller
  154.  
  155. strip_line endp
  156.  
  157. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  158. get_line proc    near
  159.  
  160. ; Routine to get a line from the standard input file, leaving it
  161. ; in line_buf with its length in line_len.  line_len will be zero 
  162. ; on end-of-file.
  163. ; no registers preserved
  164.  
  165. getnext:
  166.         call    getch           ; get next input character
  167.         jz      eol             ; zero when no more input
  168.         push    ax              ; save character
  169.         call    write           ; save in line buffer
  170.         pop     ax              ; restore character
  171.         cmp     al,.LF          ; end-of-line yet?
  172.         jne     getnext         ; jump if not LF
  173. eol:                            ; here on eol or possibly eof
  174.         ret                     ; return to caller
  175. get_line endp
  176.  
  177. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  178. check_dos_version proc  near
  179.  
  180. ; Routine to check for DOS version 2.00 or later.  Aborts with message 
  181. ; if not so.
  182. ; No registers preserved
  183.  
  184.         mov     ah,$DOS_GETVERSION
  185.         int     $DOS
  186.         xchg    ah,al
  187.         cmp     ax,0200h        ; DOS 2.00 or later?
  188.         jnb     cont            ; jump if version >= 2.00
  189.         mov     dx,offset baddos
  190.         mov     ah,$DOS_STROUT
  191.         int     $DOS            ; print string to standard output
  192.         int     $HALT           ; terminate early version of DOS
  193. cont:   
  194.         ret
  195.  
  196. baddos  db      "DESEQ: Incorrect DOS version"
  197.         db      " -- must run under DOS 2.00 or later"
  198.         db      .CR,.LF,"$"
  199.  
  200. check_dos_version endp
  201.  
  202. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  203. getch   proc    near
  204.  
  205. ; Routine to get next character from standard input in al.
  206. ; Returns with zero flag set on end-of-file, clear otherwise
  207. ; No registers are preserved
  208.  
  209.         mov     bp,inbuf_prev   ; Pointer to next available byte in buffer
  210.         cmp     bp,inbuf_len    ; Bytes left in buffer?
  211.         jl      noread          ; Yes, no need to read more yet
  212.         mov     ah,$DOS_READ2   ; string read code
  213. if DEBUG 
  214.         mov     bx,debugin      ; file handle
  215. else
  216.         mov     bx,$STDIN       ; file handle
  217. endif
  218.         mov     cx,MAXINBUF     ; count of bytes to read
  219.         mov     dx,offset inbuf ; buffer address
  220.         int     $DOS            ; read a block of characters
  221.         mov     inbuf_len,ax    ; number of bytes actually read
  222.         mov     inbuf_prev,0    ; Point to last byte returned
  223.         or      ax,ax           ; test number of bytes obtained
  224.         jz      done            ; return with zero flag set on EOF
  225.  
  226. noread:
  227.         mov     bp,inbuf_prev   ; offset of next character available
  228.         mov     al,inbuf[bp]    ; get the character from the buffer
  229.         inc     inbuf_prev      ; increment byte pointer (and set condition 
  230.                                 ; flag to non-zero)
  231. done:
  232.         ret                     ; return to caller with zero/non-zero flag set
  233.  
  234. getch   endp
  235.         
  236. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  237. write   proc    near
  238.  
  239. ; Routine to write the character in al to the line buffer.  If the
  240. ; buffer is filled, it is automatically written to the standard 
  241. ; output file by a call to write_line and an error message is issued
  242. ; noting the overflow.  Characters are not lost in the output, but
  243. ; processing on the current line will not be correct.
  244. ; No registers are preserved
  245.  
  246.         mov     bp,linbuf_len   ; offset of next available slot in buffer
  247.         cmp     bp,MAXLINBUF    ; buffer full yet?
  248.         jl      nowrite         ; no, just add to buffer
  249.         push    ax              ; yes, save character
  250.         call    write_line      ; then write the buffer        
  251.         push    bx              ; save registers
  252.         push    cx
  253.         push    dx
  254.         mov     ah,$DOS_WRITE2  ; and write an error message
  255.         mov     bx,$STDERR
  256.         mov     cx,linemsg_len
  257.         mov     dx,offset linemsg
  258.         int     $DOS
  259.         pop     dx              ; restore registers
  260.         pop     cx
  261.         pop     bx
  262.         pop     ax              ; and restore the character
  263.         mov     bp,0            ; new output buffer length in index register
  264.         mov     linbuf_len,bp   ; and storage
  265.  
  266. nowrite:                        ; here with bp pointing to offset of next char
  267.         mov     linbuf[bp],al   ; save the character
  268.         inc     linbuf_len      ; increment output buffer length
  269.         ret                     ; return to caller
  270.  
  271. linemsg db      "%Long line overflows buffer - processing incomplete",.CR,.LF
  272. linemsg_len equ  $-linemsg
  273.  
  274. write   endp
  275.  
  276. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  277. write_line proc    near
  278.  
  279. ; Routine to write the line buffer to the output buffer.  Any NUL's found 
  280. ; are discarded.
  281. ; No registers are preserved.
  282.  
  283.         mov     cx,linbuf_len   ; current line length
  284.         jcxz    wrdone          ; exit if no characters left to write
  285.         mov     si,offset linbuf; line buffer address
  286.         mov     bx,outbuf_len   ; old output buffer length
  287.         lea     di,outbuf[bx]   ; address of next available char in output
  288.         cld                     ; clear direction flag to increment si and di
  289.  
  290. mvbuff:                         ; copy the buffer discarding NULs
  291.         lodsb                   ; character from [si] to al, increment si
  292.         cmp     al,.NUL         ; NUL?
  293.         je      mvloop          ; yes, skip output
  294.         cmp     bx,MAXOUTBUF    ; still space in output buffer?
  295.         jl      mvchar          ; yes, store the character
  296.         call    write_buf       ; no, empty the buffer
  297.         mov     bx,outbuf_len   ; old output buffer length
  298.  
  299. mvchar:
  300.         stosb                   ; character from al to [di], increment di
  301.         inc     bx              ; count the character
  302.  
  303. mvloop:
  304.         loop    mvbuff          ; decrement cx, and loop while cx > 0
  305.  
  306. wrdone:
  307.         mov     outbuf_len,bx   ; update output buffer length
  308.         mov     linbuf_len,0    ; indicate empty buffer
  309.         ret                     ; return to caller
  310. write_line endp
  311.  
  312. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  313. write_buf proc   near
  314.  
  315. ; Routine to write outbuf buffer to the standard output file.
  316. ; All registers are preserved.
  317. ; Error returns from DOS (e.g. disk full) result in an error message
  318. ; and immediate termination.
  319.  
  320.         push    ax              ; save registers
  321.         push    bx
  322.         push    cx
  323.         push    dx
  324.         mov     ah,$DOS_WRITE2
  325.         mov     bx,$STDOUT      ; file handle
  326.         mov     cx,outbuf_len   ; count of bytes to write
  327.         jcxz    writeok         ; exit if nothing to write
  328.         mov     dx,offset outbuf; buffer address
  329.         int     $DOS            ; write the buffer
  330.         jnc     writeok
  331.         mov     ah,$DOS_WRITE2  ; write failed, issue message
  332.         mov     bx,$STDERR      ; file handle
  333.         mov     cx,writemsg_len ; count
  334.         mov     dx,offset writemsg      ; buffer
  335.         int     $DOS
  336.         mov     ah,$DOS_EXIT
  337.         mov     al,1            ; return code
  338.         int     $DOS            ; abort
  339.  
  340. writeok:
  341.         mov     outbuf_len,0    ; show empty buffer
  342.         pop     dx              ; restore registers
  343.         pop     cx
  344.         pop     bx
  345.         pop     ax
  346.         ret
  347.  
  348. writemsg db     "?Unrecoverable write error on standard output file",.CR,.LF
  349.         db      " Disk probably full",.CR,.LF
  350. writemsg_len equ $-writemsg
  351.         
  352. write_buf endp
  353.  
  354. assume  cs:deseqc,ds:deseqc,es:deseqc,ss:deseqc
  355. check_seq proc near
  356.  
  357. ; Routine to check that we have 5 digits followed by a tab, and if
  358. ; so, replace it by NULs.  On entry, si points to character FOLLOWING
  359. ; one with bit 8 set, and al contains the latter character.
  360. ; Preserves all registers
  361.  
  362.         push    bx              ; save bx
  363.         push    ax              ; and ax
  364.         cmp     byte ptr [si],.HT       ; check for following tab
  365.         jne     check_done      ; jump if not tab
  366.  
  367.         mov     bx,-5           ; loop count
  368.  
  369. check_dig:                      ; loop testing for digits
  370.         mov     al,[si+bx]      ; get digit
  371.         cmp     bx,-1           ; digit before tab?
  372.         jne     no_clear        ; jump if not
  373.         and     al,7FH          ; yes, clear high bit - nnnnN<tab>
  374.  
  375. no_clear:
  376.         cmp     al,.DIGIT0
  377.         jb      check_done      ; not a digit
  378.         cmp     al,.DIGIT9      ;
  379.         ja      check_done      ; not a digit
  380.         inc     bx              ; was digit, bx = bx + 1
  381.         jl      check_dig       ; loop until bx = 0
  382.  
  383.         mov     byte ptr [si-5],.NUL    ; set the nnnnn<TAB> field to NULs
  384.         mov     byte ptr [si-4],.NUL
  385.         mov     byte ptr [si-3],.NUL
  386.         mov     byte ptr [si-2],.NUL
  387.         mov     byte ptr [si-1],.NUL
  388.         mov     byte ptr [si],.NUL
  389.  
  390. check_done:
  391.         pop     ax              ; restore ax
  392.         pop     bx              ; restore bx
  393.         ret                     ; return to caller
  394. check_seq endp
  395.  
  396. deseqc  ends
  397.         end     deseq
  398.